import { Context, Next } from 'hono'
import { ValidationError } from '@/middleware/errorHandler'

// 简单的multipart/form-data解析器
export interface UploadedFile {
  name: string
  filename: string
  data: Buffer
  mimetype: string
  size: number
}

export interface ParsedFormData {
  fields: Record<string, string>
  files: Record<string, UploadedFile>
}

// 解析multipart/form-data
export const parseMultipartFormData = async (
  body: ArrayBuffer,
  contentType: string
): Promise<ParsedFormData> => {
  const boundary = contentType.split('boundary=')[1]
  if (!boundary) {
    throw new ValidationError('Invalid multipart boundary')
  }

  const buffer = Buffer.from(body)
  const boundaryBuffer = Buffer.from(`--${boundary}`)
  const endBoundaryBuffer = Buffer.from(`--${boundary}--`)

  const parts: Buffer[] = []
  let start = 0

  // 分割multipart数据
  while (start < buffer.length) {
    const boundaryIndex = buffer.indexOf(boundaryBuffer, start)
    if (boundaryIndex === -1) break

    const nextBoundaryIndex = buffer.indexOf(boundaryBuffer, boundaryIndex + boundaryBuffer.length)
    const endBoundaryIndex = buffer.indexOf(endBoundaryBuffer, boundaryIndex)

    let end: number
    if (nextBoundaryIndex !== -1 && (endBoundaryIndex === -1 || nextBoundaryIndex < endBoundaryIndex)) {
      end = nextBoundaryIndex
    } else if (endBoundaryIndex !== -1) {
      end = endBoundaryIndex
    } else {
      break
    }

    if (boundaryIndex + boundaryBuffer.length < end) {
      const part = buffer.slice(boundaryIndex + boundaryBuffer.length, end)
      if (part.length > 4) { // 至少包含\r\n\r\n
        parts.push(part)
      }
    }

    start = end
  }

  const fields: Record<string, string> = {}
  const files: Record<string, UploadedFile> = {}

  // 解析每个part
  for (const part of parts) {
    const headerEndIndex = part.indexOf(Buffer.from('\r\n\r\n'))
    if (headerEndIndex === -1) continue

    const headerBuffer = part.slice(0, headerEndIndex)
    const bodyBuffer = part.slice(headerEndIndex + 4)

    const headers = headerBuffer.toString('utf8')
    const dispositionMatch = headers.match(/Content-Disposition:\s*form-data;\s*name="([^"]+)"(?:;\s*filename="([^"]*)")?/i)
    
    if (!dispositionMatch) continue

    const fieldName = dispositionMatch[1]
    const filename = dispositionMatch[2]

    if (filename !== undefined) {
      // 这是一个文件
      const contentTypeMatch = headers.match(/Content-Type:\s*([^\r\n]+)/i)
      const mimetype = contentTypeMatch ? contentTypeMatch[1].trim() : 'application/octet-stream'

      files[fieldName] = {
        name: fieldName,
        filename,
        data: bodyBuffer.slice(0, -2), // 移除末尾的\r\n
        mimetype,
        size: bodyBuffer.length - 2
      }
    } else {
      // 这是一个普通字段
      fields[fieldName] = bodyBuffer.slice(0, -2).toString('utf8') // 移除末尾的\r\n
    }
  }

  return { fields, files }
}

// 文件上传中间件
export const uploadMiddleware = (options?: {
  maxFileSize?: number
  allowedMimeTypes?: string[]
}) => {
  const maxFileSize = options?.maxFileSize || 100 * 1024 * 1024 // 100MB
  const allowedMimeTypes = options?.allowedMimeTypes || [
    'application/zip',
    'application/x-zip-compressed',
    'application/octet-stream'
  ]

  return async (c: Context, next: Next) => {
    const contentType = c.req.header('content-type')
    
    if (!contentType || !contentType.includes('multipart/form-data')) {
      await next()
      return
    }

    try {
      const body = await c.req.arrayBuffer()
      const formData = await parseMultipartFormData(body, contentType)

      // 验证文件
      for (const [fieldName, file] of Object.entries(formData.files)) {
        // 检查文件大小
        if (file.size > maxFileSize) {
          throw new ValidationError(`File ${fieldName} is too large. Maximum size is ${maxFileSize} bytes.`)
        }

        // 检查文件类型
        if (allowedMimeTypes.length > 0 && !allowedMimeTypes.includes(file.mimetype)) {
          throw new ValidationError(`File ${fieldName} has invalid type. Allowed types: ${allowedMimeTypes.join(', ')}`)
        }
      }

      // 将解析的数据添加到上下文
      c.set('formData', formData)
      
      await next()
    } catch (error) {
      if (error instanceof ValidationError) {
        throw error
      }
      throw new ValidationError('Failed to parse multipart form data')
    }
  }
}

// 获取上传的文件
export const getUploadedFile = (c: Context, fieldName: string): UploadedFile | undefined => {
  const formData = c.get('formData') as ParsedFormData | undefined
  return formData?.files[fieldName]
}

// 获取表单字段
export const getFormField = (c: Context, fieldName: string): string | undefined => {
  const formData = c.get('formData') as ParsedFormData | undefined
  return formData?.fields[fieldName]
}
